﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Dynamic;
using System.Xml;

namespace DynamicConfigurationManager
{
    public static class DynamicConfigurationManager
    {
        private static readonly object lockObj = new object();

        ///<summary>
        ///</summary>
        public static dynamic Setting { get; } = new DynamicSetting();

        ///<summary>
        ///</summary>
        public static Dictionary<string, string> AppSettings
        {
            get
            {
                lock ( lockObj )
                {
                    return (Dictionary<string, string>)ConfigurationManager.GetSection( "DynamicConfigurationSection" );
                }
            }
        }

        ///<summary>
        ///</summary>
        public static string Log => LogHelper.Entry;

        ///<summary>
        ///</summary>
        [Obsolete( "LogEnabled is no longer used", false )]
        public static bool LogEnabled { set; get; }

        /// <summary>
        ///  Get database connection settings for environment from DynamicConfigurationManager
        /// </summary>
        /// <param name="dynamicConnectionAliasKey"></param>
        /// <param name="throwOnNotFound"></param>
        /// <returns></returns>
        public static ConnectionStringSettings ConnectionStringSetting( string dynamicConnectionAliasKey, bool throwOnNotFound = false )
        {
            if( !throwOnNotFound && ( AppSettings?[dynamicConnectionAliasKey] == null ) )
            {
                return null;
            }
            return ConfigurationManager.ConnectionStrings[AppSettings[dynamicConnectionAliasKey]];
        }

        /// <summary>
        ///  Get database connection string for environment from DynamicConfigurationManager
        /// </summary>
        /// <param name="dynamicConnectionAliasKey"></param>
        /// <param name="throwOnNotFound"></param>
        /// <returns></returns>
        public static string ConnectionString( string dynamicConnectionAliasKey, bool throwOnNotFound = false )
        {
            var cx = ConnectionStringSetting( dynamicConnectionAliasKey, throwOnNotFound );
            return cx?.ConnectionString;
        }

        ///<summary>
        ///</summary>
        ///<param name="xpath"></param>
        ///<returns></returns>
        public static Dictionary<string, string> GetSection( string xpath )
        {
            return (Dictionary<string, string>)ConfigurationManager.GetSection( xpath );
        }

        ///<summary>
        ///</summary>
        ///<param name="configFile"></param>
        ///<param name="xpath"></param>
        ///<returns></returns>
        public static Dictionary<string, string> GetSection( string configFile, string xpath )
        {
            // If user specified appSettings, use Dynamic Config instead
            if( xpath == null || xpath.ToUpper() == "APPSETTINGS" )
            {
                xpath = "DynamicConfigurationSection";
            }

            // Open config file as XML
            var doc = new XmlDocument();
            doc.Load( configFile );

            // Get the section name as an XML node
            var configNode = doc.SelectSingleNode( "configuration" );
            var node = configNode.SelectSingleNode( xpath );

            // Use the DynamicConfigSectionHandler to parse the section
            var handler = new DynamicConfigurationSectionHandler();
            return (Dictionary<string, string>)handler.Create( null, null, node );
        }

        private class DynamicSetting : DynamicObject
        {
            public override bool TryGetMember( GetMemberBinder binder, out object result )
            {
                result = null;
                var v = AppSettings[binder.Name];
                if( v != null )
                {
                    result = v;
                    return true;
                }
                return false;
            }
        }
    }
}